home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 5 / Apprentice-Release5.iso / Environments / Frontier 4.0.1 / Frontier SDK 4.0b2 / Sample Code / Frontier Do-Script / Component Do-Script / main.c < prev   
Encoding:
C/C++ Source or Header  |  1994-07-20  |  9.6 KB  |  488 lines  |  [TEXT/CWIE]

  1.  
  2. /*© copyright 1991-96 UserLand Software, Inc. All Rights Reserved.*/
  3.  
  4.  
  5. /*
  6. Drives Frontier's component "do-script" handler. You can send any valid Frontier 
  7. script across this channel. 
  8.  
  9. This program starts by sending a script with a syntax error, to test the error
  10. reporting mechanism.
  11.  
  12. This is a very bare bones program with one window and no menu bar. To quit
  13. just close the window.
  14.  
  15. It's much faster than the Apple Event-based version!
  16. */
  17.  
  18.  
  19. #include <AppleEvents.h>
  20. #include <Components.h>
  21. #include <GestaltEqu.h>
  22. #include <OSA.h>
  23.  
  24. #define stringlength(s) (s [0])
  25.  
  26. WindowPtr mainwindow = nil; /*the menu sharing test window*/
  27.  
  28. Str255 windowmessage; /*the message that's displayed in the main window*/
  29.     
  30.     
  31.  
  32.  
  33. static void initmacintosh (void) {
  34.  
  35.     /*
  36.     the magic stuff that every Macintosh application needs to do 
  37.     before doing anything else.
  38.     */
  39.  
  40.     register short i;
  41.         
  42.     MaxApplZone ();
  43.     
  44.     InitGraf (&qd.thePort);
  45.     
  46.     InitFonts ();
  47.     
  48.     FlushEvents (everyEvent, 0);
  49.     
  50.     InitWindows ();
  51.     
  52.     InitMenus ();
  53.     
  54.     TEInit ();
  55.     
  56.     InitDialogs (0L);
  57.     
  58.     InitCursor ();
  59.     
  60.     for (i = 0; i < 5; i++) { /*register with Multifinder*/
  61.         
  62.         EventRecord ev;
  63.         
  64.         EventAvail (everyEvent, &ev); /*see TN180 -- splash screen*/
  65.         } /*for*/
  66.         
  67.     DrawMenuBar ();
  68.     } /*initmacintosh*/
  69.  
  70.  
  71. static void copystring (Str255 source, Str255 dest) {
  72.  
  73.     /*
  74.     create a copy of source in dest.  copy the length byte and
  75.     all the characters in the source string.
  76.  
  77.     assume the strings are pascal strings, with the length byte in
  78.     the first character of the string.
  79.     */
  80.  
  81.     register short i, len;
  82.     
  83.     len = (short) source [0];
  84.     
  85.     for (i = 0; i <= len; i++) 
  86.         dest [i] = source [i];
  87.     } /*copystring*/
  88.  
  89.  
  90. static Boolean pushstring (Str255 bssource, Str255 bsdest) {
  91.  
  92.     register short lensource = bssource [0];
  93.     register short lendest = bsdest [0];
  94.     register char *psource, *pdest;
  95.     
  96.     if ((lensource + lendest) > 255)
  97.         return (false);
  98.         
  99.     pdest = (char *) bsdest + (char) lendest + 1;
  100.     
  101.     psource = (char *) bssource + 1;
  102.     
  103.     bsdest [0] += (char) lensource;
  104.     
  105.     while (lensource--) *pdest++ = *psource++;
  106.     
  107.     return (true);
  108.     } /*pushstring*/
  109.     
  110.     
  111. static Boolean pushlong (long num, Str255 bsdest) {
  112.  
  113.     Str255 bsint;
  114.     
  115.     NumToString (num, bsint);
  116.     
  117.     return (pushstring (bsint, bsdest));
  118.     } /*pushlong*/
  119.     
  120.  
  121. static void ellipsize (Str255 s, short width) {
  122.  
  123.     /*
  124.     if the string fits inside the given number of pixels, fine -- do nothing
  125.     and return.
  126.     
  127.     if not, return a string that does fit, with ellipses representing the 
  128.     deleted characters.  ellipses are generated by pressing option-semicolon.
  129.     */
  130.     
  131.     register char len;
  132.     register short newwidth;
  133.     
  134.     if ((newwidth = StringWidth (s)) <= width) /*nothing to do, the string fits*/
  135.         return;
  136.     
  137.     len = s [0]; /* current length in characters*/
  138.     
  139.     width -= CharWidth ('…'); /* subtract width of ellipses*/
  140.         
  141.     do { /*until it fits (or we run out of characters)*/
  142.     
  143.         newwidth -= CharWidth (s [len]);
  144.         
  145.         --len;
  146.     } while ((newwidth > width) && (len != 0));
  147.     
  148.     ++len; /*make room for the ellipses*/
  149.     
  150.     s [len] = '…'; 
  151.     
  152.     s [0] = (char) len;
  153.     } /*ellipsize*/
  154.  
  155.  
  156. static void centerstring (Rect r, Str255 s) {
  157.     
  158.     /*
  159.     draw the string in the current font, size and style, centered inside
  160.     the indicated rectangle.
  161.     */
  162.     
  163.     register short rh = r.bottom - r.top;
  164.     register short rw = r.right - r.left;
  165.     register short h, v;
  166.     FontInfo fi;
  167.     
  168.     GetFontInfo (&fi);
  169.     
  170.     ellipsize (s, rw); /*make sure it fits inside the rectangle, width-wise*/
  171.     
  172.     h = r.left + ((rw - StringWidth (s)) / 2);
  173.     
  174.     v = r.top + ((rh - (fi.ascent + fi.descent)) / 2) + fi.ascent;
  175.     
  176.     MoveTo (h, v);
  177.     
  178.     ClipRect (&r);
  179.     
  180.     DrawString (s);
  181.     } /*centerstring*/
  182.  
  183.  
  184. static void setfontsizestyle (short fontnum, short fontsize, short fontstyle) {
  185.  
  186.     TextFont (fontnum);
  187.     
  188.     TextSize (fontsize);
  189.     
  190.     TextFace (fontstyle);
  191.     } /*setfontsizestyle*/
  192.     
  193.     
  194. static void updatemainwindow (void) {
  195.     
  196.     Rect r;
  197.     Str255 s;
  198.     
  199.     r = (*mainwindow).portRect;
  200.     
  201.     EraseRect (&r);
  202.     
  203.     setfontsizestyle (helvetica, 12, 0);
  204.     
  205.     centerstring (r, windowmessage);
  206.     
  207.     NumToString (FreeMem () / 1024, s);
  208.     
  209.     MoveTo (r.left + 3, r.bottom - 3);
  210.     
  211.     setfontsizestyle (geneva, 9, 0);
  212.     
  213.     DrawString (s);
  214.     
  215.     DrawString ("\pK");
  216.     } /*updatemainwindow*/
  217.     
  218.     
  219. static void setwindowmessage (Str255 script, Str255 result) {
  220.     
  221.     copystring (script, windowmessage);
  222.             
  223.     pushstring ("\p returns ", windowmessage);
  224.             
  225.     pushstring (result, windowmessage);
  226.     
  227.     pushstring ("\p", windowmessage);
  228.             
  229.     SetPort (mainwindow);
  230.     
  231.     updatemainwindow ();
  232.     } /*setwindowmessage*/
  233.  
  234.  
  235. static Boolean initmainwindow (void) {
  236.     
  237.     register WindowPtr w;
  238.     
  239.     w = mainwindow = GetNewWindow (128, nil, (WindowPtr) -1);
  240.     
  241.     if (w == nil)
  242.         return (false);
  243.     
  244.     ShowWindow (w);
  245.     
  246.     return (true);
  247.     } /*initmainwindow*/
  248.  
  249.  
  250. static Boolean stringtotext (Str255 s, Handle *htext) {
  251.     
  252.     register long len;
  253.     register Handle h;
  254.     
  255.     len = s [0];
  256.     
  257.     h = NewHandle (len);
  258.     
  259.     if (h == nil)
  260.         return (false);
  261.         
  262.     BlockMove (&s [1], *h, len);
  263.     
  264.     *htext = h;
  265.     
  266.     return (true);
  267.     } /*stringtotext*/
  268.     
  269.     
  270. static Boolean texttostring (Handle htext, Str255 s) {
  271.     
  272.     long len;
  273.     
  274.     len = GetHandleSize (htext);
  275.     
  276.     if (len > 255)
  277.         len = 255;
  278.         
  279.     BlockMove (*htext, &s [1], len);
  280.     
  281.     s [0] = (char) len;
  282.     
  283.     return (true);
  284.     } /*texttostring*/
  285.     
  286.  
  287. static Boolean FrontierDoScript (Str255 script, Str255 returns) {
  288.     
  289.     /*
  290.     Executes a Do Script message, using Frontier's UserTalk component 
  291.     interface. The first parameter contains a short script to be run. 
  292.     The second parameter is the string that Frontier returned as the value 
  293.     generated by running the script. 
  294.     
  295.     Returns true if we were able to send the message to Frontier, and Frontier
  296.     was able to compile and run the script and return a value. FrontierDoScript 
  297.     returns false if Frontier isn't running, or if the script didn't compile or 
  298.     if there was a communications error.
  299.     
  300.     Frontier is not limited to running 255-character scripts or returning 
  301.     255-character returned values. This routine can easily be enhanced to handle 
  302.     larger scripts and returned values.
  303.     
  304.     Note that this sample code tests for the Component Manager and connects to 
  305.     the script server each time a script is executed. In production code, better 
  306.     performance can be obtained by keeping the component instance open until 
  307.     you're done with it.
  308.     */
  309.     
  310.     register OSErr ec;
  311.     ComponentInstance scriptcomp;
  312.     AEDesc scriptdesc;
  313.     AEDesc resultdesc = {typeNull, nil};
  314.     long result;
  315.     
  316.     ec = Gestalt (gestaltComponentMgr, &result);
  317.     
  318.     if ((ec != noErr) || (result == 0)) {
  319.         
  320.         copystring ("\pThe Component Manager isn’t present. This application requires System 7.1 or QuickTime.", returns);
  321.         
  322.         return (false);
  323.         }
  324.     
  325.     ec = AECreateDesc (typeChar, (Ptr) &script [1], stringlength (script), &scriptdesc);
  326.     
  327.     if (ec != noErr)
  328.         return (false);
  329.     
  330.     scriptcomp = OpenDefaultComponent (kOSAComponentType, 'LAND');
  331.     
  332.     if (scriptcomp == nil)  { /*couldn't connect to component*/
  333.         
  334.         AEDisposeDesc (&scriptdesc);
  335.         
  336.         copystring ("\pCouldn’t open the UserTalk scripting component.", returns);
  337.         
  338.         return (false);
  339.         }
  340.     
  341.     ec = OSADoScript (scriptcomp, &scriptdesc, kOSANullScript, typeChar, kOSANullMode, &resultdesc);
  342.     
  343.     AEDisposeDesc (&scriptdesc);
  344.     
  345.     switch (ec) {
  346.         
  347.         case noErr: /*script ran without error*/
  348.             
  349.             texttostring (resultdesc.dataHandle, returns);
  350.             
  351.             break;
  352.         
  353.         case errOSAScriptError: /*error during script execution*/ 
  354.             
  355.             if (OSAScriptError (scriptcomp, kOSAErrorMessage, typeChar, &resultdesc) == noErr)
  356.                 texttostring (resultdesc.dataHandle, returns);
  357.             else
  358.                 copystring ("\pThe script generated an error, but no message was provided.", returns);
  359.             
  360.             break;
  361.         
  362.         default: /*error trying to run the script*/
  363.         
  364.             copystring ("\pComponent Manager error. Its code number is ", returns);
  365.             
  366.             pushlong (ec, returns);
  367.             
  368.             pushstring ("\p.", returns);
  369.             
  370.             break;
  371.         }
  372.     
  373.     AEDisposeDesc (&resultdesc);
  374.     
  375.     CloseComponent (scriptcomp);
  376.     
  377.     return (ec == noErr);
  378.     } /*FrontierDoScript*/
  379.     
  380.     
  381. static void handledrag (EventRecord ev, WindowPtr w) {
  382.     
  383.     Rect r;
  384.  
  385.     r = qd.screenBits.bounds; 
  386.    
  387.     r.top = r.top + GetMBarHeight (); 
  388.                
  389.     r.left = r.left + 4;  
  390.                
  391.     r.right = r.right - 4;
  392.                
  393.     r.bottom = r.bottom - 4;
  394.              
  395.     DragWindow (w, ev.where, &r);   
  396.     } /*handledrag*/
  397.     
  398.     
  399. static Boolean exitprogram (void) {
  400.     
  401.     /*
  402.     returns true if the user clicks in the go-away box.
  403.     */
  404.     
  405.     EventRecord ev;
  406.     WindowPtr w;
  407.     
  408.     if (!WaitNextEvent (everyEvent, &ev, 1, nil))
  409.         return (false);
  410.     
  411.     if (ev.what != mouseDown)
  412.         return (false);
  413.         
  414.     switch (FindWindow (ev.where, &w)) {
  415.     
  416.         case inGoAway: /*click in go-away box to exit program*/
  417.             return (TrackGoAway (w, ev.where));
  418.         
  419.         case inSysWindow:
  420.             SystemClick (&ev, w); 
  421.             
  422.             return (false);
  423.         
  424.         case inDrag:
  425.             handledrag (ev, w);
  426.             
  427.             return (false);
  428.             
  429.         } /*switch*/
  430.         
  431.     return (false); /*don't exit the program*/
  432.     } /*exitprogram*/
  433.  
  434.  
  435. static void waitseconds (long n) {
  436.     
  437.     register long endticks;
  438.     
  439.     endticks = TickCount () + (n * 60);
  440.     
  441.     while (TickCount () < endticks)
  442.         SystemTask ();
  443.     } /*waitseconds*/
  444.  
  445.  
  446. void main (void) {
  447.     
  448.     Str255 script, result;
  449.     Boolean error;
  450.     register short i;
  451.     
  452.     initmacintosh ();
  453.     
  454.     initmainwindow (); 
  455.     
  456.     copystring ("\p94 + ", script);
  457.     
  458.     if (FrontierDoScript (script, result))
  459.         copystring ("\pFrontierDoScript should have returned false.", result);
  460.     
  461.     setwindowmessage (script, result); /*should say "Can't compile this script..."*/
  462.     
  463.     waitseconds (1); /*give user a chance to see error message*/
  464.     
  465.     for (i = 1; i <= 50; ++i) {
  466.         
  467.         if (exitprogram ()) /*returns true if user clicks in go away box*/
  468.             return;
  469.         
  470.         copystring ("\pstates.nthState (", script);
  471.         
  472.         pushlong (i, script);
  473.         
  474.         pushstring ("\p)", script);
  475.         
  476.         error = !FrontierDoScript (script, result);
  477.         
  478.         setwindowmessage (script, result);
  479.         
  480.         if (error)
  481.             break;
  482.         } /*while*/
  483.     
  484.     waitseconds (2); /*give user a chance to see the final result*/
  485.     } /*main*/
  486.  
  487.  
  488.